/**
 * 
 */
package uk.ac.ebi.curtain.utils.file.impl;

import java.io.IOException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import uk.ac.ebi.curtain.utils.file.EntryMapper;
import uk.ac.ebi.curtain.utils.file.EntryMapperBean;
import uk.ac.ebi.curtain.utils.file.FileInfo;
import uk.ac.ebi.curtain.utils.io.impl.BufferedRaf;

/**
 * @author mhaimel
 *
 */
public class FastqParser extends AbstractParser {
	
	private Log log = LogFactory.getLog(this.getClass());

	@Override
	public void parseNEntry(int nCnt, BufferedRaf in, FileInfo info,EntryMapper mapper) throws IOException{
		int lineCnt = 0;
		int iCnt = 0;
		String id = StringUtils.EMPTY;
		String header = StringUtils.EMPTY;
		String annot = StringUtils.EMPTY;
		StringBuffer seq = new StringBuffer();	
		StringBuffer qual = new StringBuffer();	
		String line = StringUtils.EMPTY;

		long nextPos = in.getFilePointer();
		long prevPos = nextPos;
		long currEntryPos = nextPos;
		
		while((nCnt < 0 || nCnt > iCnt) && (line = in.readLine2()) != null){
			prevPos = nextPos;
			nextPos = in.getFilePointer();
			++lineCnt;
			switch ((lineCnt%4)) {
			case 1: // header
				currEntryPos = prevPos;
				int wsIdx = line.indexOf(' ');
				if(wsIdx > 0){
					id = line.substring(0,wsIdx);
					header = line.substring(wsIdx).trim();					
				} else {
					header = StringUtils.EMPTY;
					id = line;
				}
				// remove @ from id
				if(id.charAt(0) == '@'){
					id = id.substring(1);
				} else {
					getLog().error("@ expected in id line " + id + " at file pointer: " + prevPos + " at " + info);
				}
				break;
			case 2:// sequence
				seq.append(line);
				break;
			case 3:// extra annotation
				annot = line.substring(1);
				break;
			case 0:// Quality line
				qual.append(line);
				++iCnt;
				addValid(currEntryPos,info,mapper, id, header, seq, annot,qual);

				// reset values
				id = null;
				header=null;
				seq.delete(0, seq.length());
				qual.delete(0, qual.length());
				annot = StringUtils.EMPTY;
				if(iCnt%1000000 == 0){
					getLog().debug(iCnt + " ...");
				}
				break;
			}
		}
	}

	private void addValid(long pos, FileInfo info, EntryMapper mapper, String id, String header,	StringBuffer seq, String annot, StringBuffer qual) {
		if(StringUtils.isNotBlank(id)
				&& null != header
				&& seq.length() > 0){
			mapper.mapEntry(new EntryMapperBean(pos,info,new String(id), new String(header), seq.toString(), annot,qual.toString()));
		}
	}
	private Log getLog(){
		return log;
	}

}
